<?php
declare (strict_types = 1);

namespace betka\makecmd;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\console\input\Option;

class SysObj extends Command
{
    /**
     * 应用基础目录
     * @var string
     */
    protected $basePath;

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('makesys')
            ->addArgument('name', Argument::REQUIRED, "The name of the class")
            ->addArgument('sysobj', Argument::OPTIONAL, "The name of the mdoule")
            ->setDescription('模块下对象创建');
    }

    protected function execute(Input $input, Output $output)
    {
        //service
        //dao
        //model
        $this->basePath = $this->app->getBasePath();
        $name = trim($input->getArgument('name'));
        $sysobj = trim($input->getArgument('sysobj')??'');
        $sysobj  = $sysobj?$sysobj:( 'sys'.$name); //sysobj为空取应用命名
        $sys = substr($sysobj, 0, 3);
        if ($sys != 'sys') {
            $output->writeln("<info>set moudle sys prefix! " . $sysobj . '=>' . $sys . "</info>");
            return;
        }
        if (!$name) {
            $output->writeln("<info>empty!</info>");
            return;
        }

        $output->writeln("<info>  start sys arg... {$name} {$sysobj} </info>");

        $preNamespace = 'app' . '\\' . $sysobj; //app\sysuser
        $className = $name;
        $className = $this->getClassName($className); //目录只支持一层

        $this->buildService($sysobj, $preNamespace, $className);
        $this->buildDao($sysobj, $preNamespace, $className);
        $this->buildModel($sysobj, $preNamespace, $className);
        // $this->buildModelTrait($toapp, $preNamespace, $className,'scope');
        // $this->buildModelTrait($toapp, $preNamespace, $className,'search');
        // $this->buildModelTrait($toapp, $preNamespace, $className,'logic');
        // $this->buildModelTrait($toapp, $preNamespace, $className,'enum');

        $output->writeln("<info>Successed</info>");
    }

    protected function getClassName(string $name): string
    {
        if (strpos($name, '\\') !== false) {
            return $name;
        }
        if (strpos($name, '/') !== false) {
            $name = str_replace('/', '\\', $name);
        }
        return $name;
    }

    /**
     * 创建目录
     * @access protected
     * @param  string $dirname 目录名称
     * @return void
     */
    protected function checkDirBuild(string $dirname): void
    {
        if (!is_dir($dirname)) {
            mkdir($dirname, 0755, true);
        }
    }

    protected function buildModel(string $toapp, string $preNamespace, string $className): void
    {

        $suffix = '';

        $namespace = trim(implode('\\', array_slice(explode('\\', $className), 0, -1)), '\\');
        $class = str_replace($namespace . '\\', '', $className);

        $filename = $this->basePath . ($toapp ? $toapp . DIRECTORY_SEPARATOR : '') . 'model' . DIRECTORY_SEPARATOR . ltrim(str_replace('\\', '/', $namespace), '/') .($namespace?DIRECTORY_SEPARATOR:''). ucfirst($class) . $suffix . '.php';

        if (!is_file($filename)) {
            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'sysstubs' . DIRECTORY_SEPARATOR . 'model.stub');
    

            $modelName = ucfirst($class).'M';
            $modelTrait = '';
            $modelTrait .= 'use '.$preNamespace . '\\' . 'model' . ($namespace ? '\\' . $namespace : '').'\\'.$class.'Trait'.'\\'.ucfirst('scope').' as ScopeTrait;'.PHP_EOL;
            $modelTrait .= 'use '.$preNamespace . '\\' . 'model' . ($namespace ? '\\' . $namespace : '').'\\'.$class.'Trait'.'\\'.ucfirst('search').' as SearchTrait;'.PHP_EOL;
            $modelTrait .= 'use '.$preNamespace . '\\' . 'model' . ($namespace ? '\\' . $namespace : '').'\\'.$class.'Trait'.'\\'.ucfirst('logic').' as LogicTrait;'.PHP_EOL;
            $modelTrait .= 'use '.$preNamespace . '\\' . 'model' . ($namespace ? '\\' . $namespace : '').'\\'.$class.'Trait'.'\\'.ucfirst('enum').' as EnumTrait;'.PHP_EOL;
            $useModelTrait = 'use ScopeTrait,SearchTrait,LogicTrait,EnumTrait;';
            $content = str_replace(
                [
                    '{%namespace%}',
                    '{%className%}',
                    '{%modelTrait%}',
                    '{%useModelTrait%}',
                    '{%table%}',
                ],
                [
                    $preNamespace . '\\' . 'model' . ($namespace ? '\\' . $namespace : ''),
                    ucfirst($class),
                    $modelTrait,
                    $useModelTrait,
                    $class,
                ],
                $content);
            $this->checkDirBuild(dirname($filename));

            file_put_contents($filename, $content);
            $this->output->writeln($filename);
        }else{
            $this->output->writeln('file exist ...'.$filename);
        }
    }

    protected function buildModelTrait(string $toapp, string $preNamespace, string $className,$type): void
    {

        $suffix = '';

        $namespace = trim(implode('\\', array_slice(explode('\\', $className), 0, -1)), '\\');
        $class = str_replace($namespace . '\\', '', $className);

        $filename = $this->basePath . ($toapp ? $toapp . DIRECTORY_SEPARATOR : '') . 'model' . DIRECTORY_SEPARATOR . ltrim(str_replace('\\', '/', $namespace), '/') . DIRECTORY_SEPARATOR .$class.'Trait'.DIRECTORY_SEPARATOR. ucfirst($type) . $suffix . '.php';

        if (!is_file($filename)) {
            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'sysstubs' . DIRECTORY_SEPARATOR . 'modelTrait.stub');
    

            $content = str_replace(
                [
                    '{%namespace%}',
                    '{%className%}',
                ],
                [
                    $preNamespace . '\\' . 'model' . ($namespace ? '\\' . $namespace : '').'\\'.$class.'Trait',
                    ucfirst($type),
                ],
                $content);
            $this->checkDirBuild(dirname($filename));

            file_put_contents($filename, $content);
            $this->output->writeln($filename);
        }else{
            $this->output->writeln('file exist ...'.$filename);
        }
    }


    protected function buildDao(string $toapp, string $preNamespace, string $className): void
    {

        $suffix = '';

        $namespace = trim(implode('\\', array_slice(explode('\\', $className), 0, -1)), '\\');
        $class = str_replace($namespace . '\\', '', $className);

        $filename = $this->basePath . ($toapp ? $toapp . DIRECTORY_SEPARATOR : '') . 'dao' . DIRECTORY_SEPARATOR . ltrim(str_replace('\\', '/', $namespace), '/') .($namespace?DIRECTORY_SEPARATOR:'') . ucfirst($class) . $suffix . '.php';

        if (!is_file($filename)) {
            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'sysstubs' . DIRECTORY_SEPARATOR . 'dao.stub');
    

            $modelName = ucfirst($class).'Model';
            $content = str_replace(
                [
                    '{%namespace%}',
                    '{%className%}',
                    '{%model%}',
                    '{%modelName%}',
                ],
                [
                    $preNamespace . '\\' . 'dao' . ($namespace ? '\\' . $namespace : ''),
                    ucfirst($class),
                    $preNamespace . '\\' . 'model' . ($namespace ? '\\' . $namespace : '').'\\'.ucfirst($class),
                    $modelName,
                ],
                $content);
            $this->checkDirBuild(dirname($filename));

            file_put_contents($filename, $content);
            $this->output->writeln($filename);
        }else{
            $this->output->writeln('file exist ...'.$filename);
        }
    }

    protected function buildService(string $toapp, string $preNamespace, string $className): void
    {

        $suffix = '';

        $namespace = trim(implode('\\', array_slice(explode('\\', $className), 0, -1)), '\\');
        $class = str_replace($namespace . '\\', '', $className);

        $filename = $this->basePath . ($toapp ? $toapp . DIRECTORY_SEPARATOR : '') . 'service' . DIRECTORY_SEPARATOR . ltrim(str_replace('\\', '/', $namespace), '/') .($namespace?DIRECTORY_SEPARATOR:'') . ucfirst($class) . $suffix . '.php';

        if (!is_file($filename)) {
            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'sysstubs' . DIRECTORY_SEPARATOR . 'service.stub');
    

            $daoName = ucfirst($class).'Dao';
            $modelName = ucfirst($class).'Model';
            $content = str_replace(
                [
                    '{%namespace%}',
                    '{%className%}',
                    '{%dao%}',
                    '{%model%}',
                    '{%daoName%}',
                    '{%modelName%}',
                ],
                [
                    $preNamespace . '\\' . 'service' . ($namespace ? '\\' . $namespace : ''),
                    ucfirst($class),
                    $preNamespace . '\\' . 'dao' . ($namespace ? '\\' . $namespace : '').'\\'.ucfirst($class),
                    $preNamespace . '\\' . 'model' . ($namespace ? '\\' . $namespace : '').'\\'.ucfirst($class),
                    $daoName,
                    $modelName,
                ],
                $content);
            $this->checkDirBuild(dirname($filename));

            file_put_contents($filename, $content);
            $this->output->writeln($filename);
        }else{
            $this->output->writeln('file exist ...'.$filename);
        }
    }



}
